//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//
// (C) Copyright 2006 Marvell International Ltd.
// All Rights Reserved
//
/******************************************************************************
**
** INTEL CONFIDENTIAL
** Copyright 2003-2005 Intel Corporation All Rights Reserved.
**
** The source code contained or described herein and all documents
** related to the source code (Material) are owned by Intel Corporation
** or its suppliers or licensors.  Title to the Material remains with
** Intel Corporation or its suppliers and licensors. The Material contains
** trade secrets and proprietary and confidential information of Intel
** or its suppliers and licensors. The Material is protected by worldwide
** copyright and trade secret laws and treaty provisions. No part of the
** Material may be used, copied, reproduced, modified, published, uploaded,
** posted, transmitted, distributed, or disclosed in any way without Intel's
** prior express written permission.
**
** No license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise. Any license under such intellectual property rights
** must be express and approved by Intel in writing.
**
**
******************************************************************************/

#include <windows.h>
#include <nkintr.h>
#include <monahans.h>
#include <Littleton.h>
#include <oal_memory.h>
#include <pcireg.h>
#include <fmd.h>
#include <bsp.h>
#include "loader.h"
#include <bootpart.h>
#include "xllp_pm.h"
#include "xllp_pm_dvfm.h"
#include "monahans_base_regs.h"
#include "xllp_defs.h"
#include "xllp_udc.h"
#include "xllp_lcd_plat.h"
#include "xllp_i2c.h"
#include "xllp_ost.h"
#include <flash_cfg.h>
#include <blcommon.h>

//Included for the SD/MMC boot option
#include "SDMMC.h"
#include "FAT.h"

#include "BLMenu.h"

extern EBOOT_CONTEXT g_EBootContext ;

static void SetIP(BSP_ARGS *pEbootCFG);
static void SetMask(BSP_ARGS *pEbootCFG);

MENU_ITEM * GetMainItem();
static BOOL SetFileName(void);
static BOOL useSDMMCBoot(char *filename);
static char *convertToUpperCase(char *filename);
static BOOL compareFileName(P_DIR_STRUCTURE pDIR, char *filename);
static void printFileData(XLLP_UINT32_T filesize);


//---------Main Menu Action-------------------------------------------------------------
extern BSP_ARGS *g_pBSPArgs ;


/***************************************************************************
*   SetFileName
*      Allows the user to enter the name of the file to be burned to flash
*   Input:
*      pEbootCFG - pointer to eboot structure
*   Output:
*      filename contains the user entered file name
*   Returns:
*      TRUE - if the download is completed
*      FALSE - otherwise
*****************************************************************************/
static BOOL SetFileName(void)
{
    WORD cwNumChars = 0;
    UINT16 InChar = 0;
    char filename[20];

    EdbgOutputDebugString ( "\r\nEnter the desired filename: ");

    while (!((InChar == 0x0d) || (InChar == 0x0a)))
    {
        InChar = OEMReadDebugByte();
        if (InChar != OEM_DEBUG_COM_ERROR && InChar != OEM_DEBUG_READ_NODATA)
        {
            // If it's not a backspace, add it to the string
            if (InChar == '.' || (InChar >= '0' && InChar <= '9')
                              || (InChar >= 'a' && InChar <= 'z')
                              || (InChar >= 'A' && InChar <= 'Z'))
            {
                if (cwNumChars < 20)
                {
                    filename[cwNumChars++] = (char)InChar;
                    OEMWriteDebugByte((BYTE)InChar);
                }
            }
            // If it's a backspace, back up
            else if (InChar == 8)
            {
                if (cwNumChars > 0)
                {
                    cwNumChars--;
                    OEMWriteDebugByte((BYTE)InChar);
                }
            }
        }
    }

    // If it's a carriage return with an empty string, don't change anything.
    if (cwNumChars)
    {
        filename[cwNumChars] = '\0';
        if(useSDMMCBoot(filename))
            return TRUE;
        else
            return FALSE;
    }
    return TRUE;
}

static BYTE *fileData = (void *)0x82101000;//the buffer for the downloaded data

/******************************************************************************
*   useSDMMCBoot
*      Initializes the SD/MMC driver, initializes the SD/MMC card, finds a file
*      on the card, and reads it into a buffer.
*   Input:
*      none
*   Output:
*      The data from a user specified file on the SD/MMC card is contained in a 
*      buffer and ready to be burned to flash.
*   Returns:
*      none
******************************************************************************/
BOOL useSDMMCBoot(char *filename)
{
    XLLP_MMC_CONTEXT_T context; //the MMC context
    char pMfpRMDb[XLLP_MFP_RM_DB_SIZE];
    P_XLLP_CLKMGR_T clkmgr;
    MBR_STRUCTURE mbr; //the master boot record
    BPB_STRUCTURE bpb; //the boot partition
    FAT_STRUCTURE fat;
    P_PARTITION activePartition; //the active partition
    READ_FAT readFAT;
    BYTE buffer[BLK_LEN], rootDir[BLK_LEN], FAT[BLK_LEN];
    DIR_STRUCTURE dir; //the current directory entry
    XLLP_UINT32_T rca, mmc_stat, sector, sectorsBeforePartition, j, readOffset;
    int i, fileFound, endRootDir, activePart, secPerClus;
    long fileSize, sectorsRead=0;

    //SD/MMC Driver Setup

    clkmgr = (P_XLLP_CLKMGR_T)
                OALPAtoVA(MONAHANS_BASE_REG_PA_CLKMGR, FALSE);
    context.pMMC1Reg = (P_XLLP_MMC_T)
                          OALPAtoVA(MONAHANS_BASE_REG_PA_MMC, FALSE);	
    context.pMMC2Reg = (P_XLLP_MMC_T)
                          OALPAtoVA(MONAHANS_BASE_REG_PA_MMC2, FALSE);
    context.pGPIOReg = (P_XLLP_GPIO_T)
                          OALPAtoVA(MONAHANS_BASE_REG_PA_GPIO, FALSE);
    context.pMFPBase = (P_XLLP_VUINT32_T)
                          OALPAtoVA(MONAHANS_BASE_REG_PA_MFP, FALSE);
    context.pOSTReg = (P_XLLP_OST_T)
                         OALPAtoVA(MONAHANS_BASE_REG_PA_OST, FALSE);

    if (XLLP_STATUS_SUCCESS != XllpMfpResourceManagerInit(pMfpRMDb)) {
        EdbgOutputDebugString("[MMC] Fail to XllpMfpResourceManagerInit()!\r\n");
        return FALSE;
    }

    context.pMFPRmDb = (P_XLLP_MFP_RM_DB_ID_T)pMfpRMDb;
    EdbgOutputDebugString("\r\nLoading the image via SDMMC Card!!!!\r\n");

    //initialize the SD/MMC slot and card
    rca = SDMMCInit(&context, clkmgr);

    //if initialization failed
    if(rca == -1)
    {
        EdbgOutputDebugString("\r\nInitialization Failed!\r\n");
        return FALSE;
    }

    EdbgOutputDebugString("\r\nInitialization Complete...\r\n");

    //End of Driver Setup

    //Start reading data off the card

    SDMMCSetBlockLength(&context, BLK_LEN);

    //read the master boot record off of the card
    SDMMCReadBlock(&context, 0, buffer);

    XllpMMCReadStatus(&context, &mmc_stat, XLLP_MMC_CONTROLLER_1);
    SDMMCGetCardStatus(&context, rca);

    getMBR(&mbr, buffer);

    //find the active partition

    activePart = findActivePartition(&mbr);

    if(activePart == PARTITION_1)
        activePartition = &mbr.partition1;
    else if(activePart == PARTITION_2)
        activePartition = &mbr.partition2;
    else if(activePart == PARTITION_3)
        activePartition = &mbr.partition3;
    else if(activePart == PARTITION_4)
        activePartition = &mbr.partition4;
    else
    {
        EdbgOutputDebugString("There are no active partitions!!!\r\n");
        activePartition = NULL;
    }

    //if there are no active partitions detected, 
    //assume it is the start of a partition
    if(activePartition == NULL)
    {
        SDMMCReadBlock(&context, 0, buffer);
        sectorsBeforePartition = 0;
    }
    //otherwise compute the sectors before the partition and read the first 
    //block of the partition
    else
    {
        sectorsBeforePartition = computeSectorsBeforePartition(activePartition);
        SDMMCReadBlock(&context, (MBR+sectorsBeforePartition)*BLK_LEN, buffer);
    }

    //find the boot block
    if(!fillBootBlockStructure(&bpb, buffer))
    {
        EdbgOutputDebugString("No valid boot block found!!!\r\n");
        return FALSE;
    }

    //find the fat data structure
    getFATDataStructure(&bpb, &fat);
    
    readOffset = 2*bpb.BPB_SecPerClus;
   
    //convert the filename to uppercase to compare
    filename = convertToUpperCase(filename); 

    EdbgOutputDebugString("Searching for file: %s\r\n", filename);
   
    SDMMCReadBlock(&context, 
        (fat.FirstRootDirSecNum+sectorsBeforePartition)*BLK_LEN, rootDir);
   
    for(j=1; j<fat.RootDirsSectors; j++)
    {
        for(i=0; i<BLK_LEN; i+=ROOT_SIZE)
        {
            //get the next directory entry
            getShortDirStructure(&dir, &rootDir[i]);
            endRootDir = FALSE;

            //check if its the desired file
            if (compareFileName(&dir, filename))
            {
                XLLP_UINT32_T firstCluster, currentFAT;

                fileFound = TRUE;

                EdbgOutputDebugString("%s found.\r\n", filename);
                EdbgOutputDebugString("Starting download...\r\n");

                //get the file size
                fileSize = dir.DIR_FileSize[3];
                fileSize = fileSize << 8;
                fileSize |= dir.DIR_FileSize[2];
                fileSize = fileSize << 8;
                fileSize |= dir.DIR_FileSize[1];
                fileSize = fileSize << 8;
                fileSize |= dir.DIR_FileSize[0];

                //calculater where the first cluster of data is located
                firstCluster = dir.DIR_FstClusLO[1];
                firstCluster = firstCluster << 8;
                firstCluster |= dir.DIR_FstClusLO[0];

                getSectorOffset(&bpb, &fat, &readFAT, firstCluster);

                //get the first block of the FAT
                SDMMCReadBlock(&context, 
                    (readFAT.ThisFATSecNum+sectorsBeforePartition)*BLK_LEN, FAT);

                currentFAT = readFAT.ThisFATSecNum;

                //determine where the next data block is by reading the FAT
                sector = *(FAT + readFAT.ThisFATEntOffset+1);
                sector = sector << 8;
                sector |= *(FAT + readFAT.ThisFATEntOffset);		   

                //download the first data cluster
                for(secPerClus = 0; secPerClus < bpb.BPB_SecPerClus; secPerClus++)
                {
                    SDMMCReadBlock(&context, (((fat.FirstDataSector+
                        firstCluster*bpb.BPB_SecPerClus)-readOffset+secPerClus)
                        +sectorsBeforePartition)*BLK_LEN, 
                        (BYTE *)fileData+sectorsRead*BLK_LEN);
                    sectorsRead++;
                }

                //keep downloading until the eno of file is reached
                while(!isEOF(fat.FATType, sector))
                {
                for(secPerClus=0; secPerClus < bpb.BPB_SecPerClus; secPerClus++)
                {
                    SDMMCReadBlock(&context, (((fat.FirstDataSector
                        +sector*bpb.BPB_SecPerClus)-readOffset+secPerClus)
                        +sectorsBeforePartition)*BLK_LEN, 
                        (BYTE *)fileData+sectorsRead*BLK_LEN);
                    sectorsRead++;
                }

                getSectorOffset(&bpb, &fat, &readFAT, sector);

                //if entry is not in current block of FAT, 
                //page in the next block of FAT
                if(readFAT.ThisFATSecNum != currentFAT)
                {
                    SDMMCReadBlock(&context, (readFAT.ThisFATSecNum
                        +sectorsBeforePartition)*BLK_LEN, FAT);
                    currentFAT = readFAT.ThisFATSecNum;
                }

                sector = *(FAT + readFAT.ThisFATEntOffset+1);
                sector = sector << 8;
                sector |= *(FAT + readFAT.ThisFATEntOffset);

                if(sectorsRead%2000 == 0)
                    EdbgOutputDebugString("%d of %d Complete!\r\n", 
                        sectorsRead*BLK_LEN, fileSize);
                }
                break;
            }
        }
        if(fileFound)
            EdbgOutputDebugString("\r\nDownload Complete!\r\n");

        if(fileFound || endRootDir)
            break;

        SDMMCReadBlock(&context, (fat.FirstRootDirSecNum
            +sectorsBeforePartition+j)*BLK_LEN, rootDir);
    }

   return TRUE;
}

/**************************************************************************
*   printFileData
*      Used for debugging - print out the contents of the fileData buffer
*   Input:
*      fileSize - the length of the file in bytes
*   Output:
*      Character representation of fileData is printed to the screen.
*   Returns:
*      none
*****************************************************************************/
static void printFileData(XLLP_UINT32_T filesize)
{
    XLLP_UINT32_T i;
    EdbgOutputDebugString("\r\n****FILESIZE = %d****\r\n", filesize);
    for(i=0; i<filesize; i++)
        EdbgOutputDebugString("%c", fileData[i]);
}


/******************************************************************************
*   convertToUpperCase
*      Converts the user entered filename to uppercase
*   Input:
*      filename - the desired file name
*   Output:
*      filename is converted to uppercase
*   Returns:
*      filename after it has been converted
******************************************************************************/
static char *convertToUpperCase(char *filename)
{
    int i;
    for(i=0; i<20; i++)
        if(filename[i] >= 'a' && filename[i] <= 'z')
            filename[i] -= 32;
    return filename;
}

/******************************************************************************
*   compareFileName
*      Compares the user entered filename with a short directory structure name
*   Input:
*      pDir - the directory entry file name
*      filename - the desired file name
*   Output:
*      none
*   Returns:
*      TRUE if the filenames are equal
*      FALSE otherwise
******************************************************************************/
static BOOL compareFileName(P_DIR_STRUCTURE pDIR, char *filename)
{
    int i;
    for(i=0; i<11; i++)
    {
        if(pDIR->DIR_Name[i] != filename[i])
        {
            if(filename[i] != '.')
                return FALSE;
            else if(filename[i] == '.' && pDIR->DIR_Name[i] != ' ')
                return FALSE;
            else
            {
                if(pDIR->DIR_Name[8] != filename[i+1])
                    return FALSE;
                else if(pDIR->DIR_Name[9] != filename[i+2] 
                    && pDIR->DIR_Name[9] != ' ')
                    return FALSE;
                else if(pDIR->DIR_Name[10] != filename[i+3] 
                    && pDIR->DIR_Name[10] != ' ')
                    return FALSE;
                else
                    return TRUE;
            }
        }
    }
    return TRUE;
}

/******************************************************************************
*   SDMMCReadData
*      Reads the specified number of bytes out of fileData starting at the 
*      given offset into the given memory location.
*   Input:
*      cbData - the length of bytes to read.
*      pbData - the destination memory address.
*      offset - the offset in which to start reading from in fileData.
*   Output:
*      none
*   Returns:
*      TRUE
******************************************************************************/
BOOL SDMMCReadData(DWORD cbData, LPBYTE pbData, DWORD offset)
{
    memcpy(pbData, &fileData[offset], cbData);

    g_EBootContext.cbData = cbData;
    g_EBootContext.pbData = pbData;

    return TRUE;
}



DWORD SetIPAddress(MENU_ITEM *pMenu)
{
    SetIP(g_pBSPArgs);
    GetMainItem();
    return 0;
}

DWORD SetIPMask(MENU_ITEM *pMenu)
{
    SetMask(g_pBSPArgs);
    GetMainItem();
    return 0;
}

extern BOOL g_DownloadImage ;

DWORD DownLoad(MENU_ITEM *pMenu)
{
    g_DownloadImage = TRUE;
    return 1;
}

static DWORD SetDelay(MENU_ITEM *pMenu)
{
    char szCount[16];
    WORD cwNumChars = 0;
    UINT16 InChar = 0;
    EBOOT_CFG *pEbootCFG=&g_pBSPArgs->eBootCFG;

    EdbgOutputDebugString("\r\nEnter maximum number of seconds to delay [1-255]: ");

    while (!((InChar == 0x0d) || (InChar == 0x0a)))
    {
        InChar = OEMReadDebugByte();
        if (InChar != OEM_DEBUG_COM_ERROR && InChar != OEM_DEBUG_READ_NODATA)
        {
            // If it's a number or a period, add it to the string
            if ((InChar >= '0' && InChar <= '9'))
            {
                if (cwNumChars < 16)
                {
                    szCount[cwNumChars++] = (char) InChar;
                    OEMWriteDebugByte((BYTE) InChar);
                }
            }
            // If it's a backspace, back up
            else if (InChar == 8)
            {
                if (cwNumChars > 0)
                {
                    cwNumChars--;
                    OEMWriteDebugByte((BYTE) InChar);
                }
            }
        }
    }

    // If it's a carriage return with an empty string, don't change anything.
    if (cwNumChars)
    {
        szCount[cwNumChars] = '\0';
        pEbootCFG->delay = atoi(szCount);
        if (pEbootCFG->delay > 255)
        {
            pEbootCFG->delay = 255;
        }
        else if (pEbootCFG->delay < 1)
        {
            pEbootCFG->delay = 1;
        }
    }

    pMenu->pParam1 = (VOID*) pEbootCFG->delay ;
    return 0;

}

DWORD InitDownloadRAM(MENU_ITEM *p)
{

    EdbgOutputDebugString("initializing RAM from 0x%X to 0x%X...", OS_RAM_IMAGE_START, OS_RAM_END);
    memset((void *) OALPAtoVA(OS_RAM_IMAGE_START, FALSE), 0xFF, OS_RAM_END - OS_RAM_IMAGE_START);
    EdbgOutputDebugString("done\r\n");
    return 0;
}

extern BOOL g_SDMMCDownload;
extern BOOL g_IPLDownload;
extern BOOL g_JumpDirectlyIntoRAM;

DWORD DownLoadFromMMC(MENU_ITEM *p)
{
    if (SetFileName())
    {
        g_SDMMCDownload = TRUE;
        g_IPLDownload = FALSE;
        g_JumpDirectlyIntoRAM = FALSE;

        return (1);
    }
    return 0;

}

DWORD LaunchFromFlash(MENU_ITEM *p)
{
    g_DownloadImage = FALSE;
    return 1;
}

DWORD ReadRTC(MENU_ITEM *p)
{
    EdbgOutputDebugString("RTC Time: 0x%X\r\n", OEMEthGetSecs());
    return 0;
}

static void SetIP(BSP_ARGS *pArgs)
{
    char szDottedD[16]; // The string used to collect the dotted decimal IP address
    WORD cwNumChars = 0;
    UINT16 InChar = 0;

    EdbgOutputDebugString("\r\nEnter new IP address: ");

    while (!((InChar == 0x0d) || (InChar == 0x0a)))
    {
        InChar = OEMReadDebugByte();
        if (InChar != OEM_DEBUG_COM_ERROR && InChar != OEM_DEBUG_READ_NODATA)
        {
            // If it's a number or a period, add it to the string
            if (InChar == '.' || (InChar >= '0' && InChar <= '9'))
            {
                if (cwNumChars < 16)
                {
                    szDottedD[cwNumChars++] = (char)InChar;
                    OEMWriteDebugByte((BYTE)InChar);
                }
            }
            // If it's a backspace, back up
            else if (InChar == 8)
            {
                if (cwNumChars > 0)
                {
                    cwNumChars--;
                    OEMWriteDebugByte((BYTE) InChar);
                }
            }
        }
    }

    // If it's a carriage return with an empty string, don't change anything.
    if (cwNumChars)
    {
        szDottedD[cwNumChars] = '\0';
        pArgs->kitl.ipAddress = inet_addr( szDottedD );
    }
}
DWORD TestAcc(MENU_ITEM *pCur)
{
	#define ACC_I2C_Address 0x1d
	XLLP_VUINT32_T *pMFP;
	P_XLLP_OST_T pOST;
	P_XLLP_I2C_T pI2C;
	XLLP_INT8_T pMfpRMDb[XLLP_MFP_RM_DB_SIZE];
	XLLP_UINT8_T writebyte[2] = {0x16, 0x01};
	XLLP_UINT8_T readbyte[3];
	EdbgOutputDebugString("Test Acc Sensor\r\n");
	
	pOST= (P_XLLP_OST_T) OALPAtoVA(MONAHANS_BASE_REG_PA_OST, FALSE);
	pI2C= (P_XLLP_I2C_T) OALPAtoVA(MONAHANS_BASE_REG_PA_I2C, FALSE);
	pMFP= (XLLP_VUINT32_T *) OALPAtoVA(MONAHANS_BASE_REG_PA_MFP, FALSE);
	
	if (XLLP_STATUS_SUCCESS!=XllpMfpResourceManagerInit(pMfpRMDb))
	{
		EdbgOutputDebugString("[failed to XllpMfpResourceManagerInit()!\r\n");
	}
		
	XllpI2cInit(pI2C, pMFP, pMfpRMDb, 0);


    XllpI2CWrite(pI2C, pOST, ACC_I2C_Address, writebyte,2,TRUE);
	while(1)
	{
		writebyte[0] = 0x06;
		XllpI2CWrite(pI2C, pOST, ACC_I2C_Address, writebyte,2,TRUE);
		XllpI2CRead(pI2C,pOST,ACC_I2C_Address,readbyte,3,TRUE);
		EdbgOutputDebugString("Read Acc Sensor X:%x,Y:%x,Z:%x\r\n",readbyte[0],readbyte[1],readbyte[2]);
		//writebyte[0] =0x07;
		//XllpI2CWrite(pI2C, pOST, ACC_I2C_Address, writebyte,1,TRUE);
		//XllpI2CRead(pI2C, pOST, ACC_I2C_Address, &readbyte, 1, TRUE);
		//EdbgOutputDebugString("Read Acc Sensor Y Value: %x\r\n",readbyte);
		//writebyte[0] = 0x08;
		//XllpI2CWrite(pI2C, pOST, ACC_I2C_Address, writebyte,1,TRUE);
		//XllpI2CRead(pI2C, pOST, ACC_I2C_Address, &readbyte, 1, TRUE);
		//EdbgOutputDebugString("Read Acc Sensor Z Value: %x\r\n",readbyte);
		XllpOstDelayMilliSeconds(pOST, 1000);
	}
}
DWORD TestMangic(MENU_ITEM *pCur)
{
#define Mag2120_I2C_Address 0x30	
	XLLP_VUINT32_T *pMFP;
	P_XLLP_OST_T pOST;
	P_XLLP_I2C_T pI2C;
	XLLP_INT8_T pMfpRMDb[XLLP_MFP_RM_DB_SIZE];
	XLLP_UINT8_T readbyte[4];
	XLLP_UINT8_T writebyte[2];
	EdbgOutputDebugString("Test Mangic Sensor!\r\n");
	
	pOST= (P_XLLP_OST_T) OALPAtoVA(MONAHANS_BASE_REG_PA_OST, FALSE);
	pI2C= (P_XLLP_I2C_T) OALPAtoVA(MONAHANS_BASE_REG_PA_I2C, FALSE);
	pMFP= (XLLP_VUINT32_T *) OALPAtoVA(MONAHANS_BASE_REG_PA_MFP, FALSE);
	
	if (XLLP_STATUS_SUCCESS!=XllpMfpResourceManagerInit(pMfpRMDb))
	{
		EdbgOutputDebugString("[failed to XllpMfpResourceManagerInit()!\r\n");
	}
		
	XllpI2cInit(pI2C, pMFP, pMfpRMDb, 0);
	while(1)
	{
		writebyte[0] = 0x00;
		writebyte[1] = 0x01;
		XllpI2CWrite(pI2C,pOST,Mag2120_I2C_Address,
		writebyte,
		sizeof(writebyte), 
		TRUE);
	XllpOstDelayMilliSeconds(pOST, 10);
	writebyte[0] = 0x01;
	XllpI2CWrite(pI2C,
		pOST,
		Mag2120_I2C_Address,
		writebyte,
		sizeof(writebyte), 
		TRUE);
	XllpI2CRead(pI2C,
	 			pOST,
	 			Mag2120_I2C_Address,
	 			readbyte,
	 			4,
	 			TRUE);
		//XllpI2CRead(pI2C, pOST, 0x60, &readbyte, 1, TRUE);
		EdbgOutputDebugString("Read Acc Sensor Value: %x %x\r\n",readbyte[0],readbyte[1]);
		EdbgOutputDebugString("Read Acc Sensor Value: %x %x\r\n",readbyte[2],readbyte[3]);
		XllpOstDelayMilliSeconds(pOST, 1000);
	}
}

static void SetMask(BSP_ARGS *pArg)
{
    char szDottedD[16]; // The string used to collect the dotted masks
    WORD cwNumChars = 0;
    UINT16 InChar = 0;

    EdbgOutputDebugString ( "\r\nEnter new subnet mask: ");

    while (!((InChar == 0x0d) || (InChar == 0x0a)))
    {
        InChar = OEMReadDebugByte();
        if (InChar != OEM_DEBUG_COM_ERROR && InChar != OEM_DEBUG_READ_NODATA)
        {
            // If it's a number or a period, add it to the string
            if (InChar == '.' || (InChar >= '0' && InChar <= '9'))
            {
                if (cwNumChars < 16)
                {
                    szDottedD[cwNumChars++] = (char)InChar;
                    OEMWriteDebugByte((BYTE)InChar);
                }
            }
            // If it's a backspace, back up
            else if (InChar == 8)
            {
                if (cwNumChars > 0)
                {
                    cwNumChars--;
                    OEMWriteDebugByte((BYTE)InChar);
                }
            }
        }
    }

    // If it's a carriage return with an empty string, don't change anything.
    if (cwNumChars)
    {
        szDottedD[cwNumChars] = '\0';
        pArg->kitl.ipMask = inet_addr( szDottedD );
    }
}

DWORD 	SetBSPArg(MENU_ITEM*);
extern MENU_ITEM g_TestMenu[];

// Number of menu items including the null entry to indicate end of list
#define NUMBER_OF_MENU_ITEMS 16
/*******************************************************************************
Main menu
*******************************************************************************/
MENU_ITEM * GetMainItem()
{
    static MENU_ITEM mainitem[NUMBER_OF_MENU_ITEMS];
    static unsigned char IPAddress[16];
    static unsigned char IPSubMask[16];
    MENU_ITEM *pItem=mainitem;

    memset(mainitem, 0, sizeof(mainitem));


    InitMenuItem(pItem++, _T('0'), _T("IP address: %u.%u.%u.%u"),SetIPAddress,
            (VOID*)(g_pBSPArgs->kitl.ipAddress&0xFF ),
            (VOID*)((g_pBSPArgs->kitl.ipAddress>>8)&0xFF),
            (VOID*)((g_pBSPArgs->kitl.ipAddress>>16)&0xFF),
            (VOID*)((g_pBSPArgs->kitl.ipAddress>>24)));

    InitMenuItem(pItem++, _T('1'), _T("Subnet Mask: %u.%u.%u.%u"),SetIPMask,
            (VOID*)(g_pBSPArgs->kitl.ipMask&0xFF) ,
            (VOID*)((g_pBSPArgs->kitl.ipMask>>8)&0xFF),
            (VOID*)((g_pBSPArgs->kitl.ipMask>>16)&0xFF),
            (VOID*)((g_pBSPArgs->kitl.ipMask>>24)));
    
    InitMenuItem(pItem++, _T('2'), _T("Boot delay: %d seconds"),SetDelay,(VOID*)g_pBSPArgs->eBootCFG.delay ,NULL,NULL,NULL);
    InitMenuItem(pItem++, _T('3'), _T("DHCP: %s"),OALBLMenuEnableMASK32,(VOID*)(g_pBSPArgs->kitl.flags&OAL_KITL_FLAGS_DHCP?L"(Enabled)":L"(Disabled)") ,&(g_pBSPArgs->kitl.flags),(VOID*)OAL_KITL_FLAGS_DHCP,NULL);
    InitMenuItem(pItem++, _T('5'), _T("Auto Download image at startup(%s)"),OALBLMenuEnableBOOL,(VOID*)(g_pBSPArgs->eBootCFG.autoDownloadImage?L"Enable":L"Disable" ) ,&(g_pBSPArgs->eBootCFG.autoDownloadImage),NULL,NULL);
    InitMenuItem(pItem++, _T('8'), _T("Initialize Download RAM"),InitDownloadRAM,NULL ,NULL,NULL,NULL);
    InitMenuItem(pItem++, _T('D'), _T("Download image now"),DownLoad,NULL ,NULL,NULL,NULL);
//    InitMenuItem(pItem++, _T('M'), _T("Download image with SDMMC Card"),DownLoadFromMMC,NULL ,NULL,NULL,NULL);
    InitMenuItem(pItem++, _T('L'), _T("Launch existing flash resident image now"),LaunchFromFlash,NULL ,NULL,NULL,NULL);
    InitMenuItem(pItem++, _T('C'), _T("Read current RTC time"),ReadRTC,NULL ,NULL,NULL,NULL);
    InitMenuItem(pItem++, _T('S'), _T("Set BSP Configuration"),SetBSPArg,NULL ,NULL,NULL,NULL);
    InitMenuItem(pItem++, _T('U'), _T("Go to image update(%s)"),OALBLMenuEnableBOOL,(VOID*)((g_pBSPArgs->bUpdateMode == TRUE) ?L"Enabled" : L"Disabled") ,&(g_pBSPArgs->bUpdateMode),NULL,NULL);	
    InitMenuItem(pItem++, _T('F'), _T("Format User Partition(%s)"),OALBLMenuEnableBOOL,(VOID*)((g_pBSPArgs->bFormatPartition == TRUE) ? L"Enabled" : L"Disabled") ,&(g_pBSPArgs->bFormatPartition),NULL,NULL);
	InitMenuItem(pItem++, _T('A'), _T("Test Acc Sensor(%s)"),TestAcc,NULL,NULL,NULL,NULL);	
    InitMenuItem(pItem++, _T('M'), _T("Test Mangic Sensor(%s)"),TestMangic,NULL,NULL,NULL,NULL);
	

#ifndef SHIP_BUILD
    InitMenuItem(pItem++, _T('T'), _T("Test Menu"),OALBLMenuShow,NULL ,g_TestMenu,NULL,NULL);
#endif
    //  Indicate the end of the list
    InitMenuItem(pItem++, L'\0',L"", NULL, NULL, NULL, NULL, NULL);
    return mainitem;

}


void BLMenu()
{
    MENU_ITEM item;
    item.text=L"%s";
    item.pParam1=_T("Eboot Main Menu");
    item.pParam2=GetMainItem();

    OALBLMenuShow(&item);
}


